package com.franklin.ideaplugin.easytesting.registry;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.franklin.ideaplugin.api.utils.ProjectUtils;
import com.franklin.ideaplugin.easytesting.rpc.RegistryCenter;
import com.franklin.ideaplugin.easytesting.rpc.entity.RegistryData;
import com.google.common.collect.Lists;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author Ye Junhui
 * @since 2023/7/28
 */
public class ApplicationScheduleFileRegistry {

    public ApplicationScheduleFileRegistry() {
        this.startExecutor();
    }

    public static ApplicationScheduleFileRegistry getInstance() {
        return ServiceManager.getService(ApplicationScheduleFileRegistry.class);
    }

    private final ConcurrentMap<Project, RegistryServer> serviceMap = new ConcurrentHashMap<>();

    private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
            runnable -> {
                Thread thread = new Thread(runnable, "easy-testing-file-registry");
                thread.setDaemon(true);
                return thread;
            }
    );

    /**
     * 业务线程池
     */
    private final ThreadPoolExecutor workPool = new ThreadPoolExecutor(
            4,
            16,
            60L,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(4000),
            r -> {
                Thread thread = new Thread(r, "easy-testing-file-registry-work-thread-" + r.hashCode());
                thread.setDaemon(true);
                return thread;
            },
            (r, executor) -> {
                throw new RuntimeException("easy-testing, file registry work pool is EXHAUSTED!");
            });

    private void startExecutor() {
        this.executor.scheduleAtFixedRate(
                () -> {
                    try {
                        Project currProject = ProjectUtils.getCurrProject();
                        if (Objects.nonNull(currProject)){
                            RegistryServer registryServer = this.serviceMap.get(currProject);
                            if (Objects.isNull(registryServer)){
                                registryServer = this.createServer(currProject);
                            }
                            registryServer.refresh();
                        }
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                },
                2, 3,
                TimeUnit.SECONDS
        );
    }

    /**
     * 先取缓存后读文件
     *
     * @param project
     * @param registryPath
     * @return
     */
    public static List<RegistryData> getRegistryData(Project project, String registryPath) {
        ApplicationScheduleFileRegistry instance = getInstance();
        RegistryServer registryServer = instance.serviceMap.get(project);
        if (Objects.isNull(registryServer)){
            registryServer = instance.createServer(project);
        }
        return registryServer.getRegistryData(registryPath);
    }

    /**
     * 创建服务
     * @param project
     * @return
     */
    private RegistryServer createServer(Project project){
        RegistryServer registryServer = new RegistryServer(RegistryCenter.getProjectRegistryPath(project),workPool);
        ApplicationScheduleFileRegistry instance = getInstance();
        instance.serviceMap.put(project,registryServer);
        return registryServer;
    }
}
